package com.lhx.product.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lhx.product.domain.PmsProductAttrRelVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：李洪祥
 * @Package：PACKAGE_NAME
 * @Project：lhx-RuoYi
 * @name：Test
 * @Date：2024/6/1 下午12:53
 */
@RestController
@RequestMapping("/test")
@Api(tags = "测试模块")
public class OkController {

    /**
     * 主函数：通过计算属性组合，来生成产品属性的组合列表。
     * 输入：字符串数组 args，通常用于接收命令行参数，本函数未使用该输入。
     * 输出：无，通过系统输出打印计算结果。
     */
    @ApiOperation(value = "分页查询商品属性列表")
    @PostMapping("findList")
    public static void main() {
        // 定义一个字符串，包含了一系列产品属性信息，每个属性包括id(属性类别ID)和name(属性名称)
        String str = "[\n" +
                "\t{\n" +
                "\t\t\"id\": 1,\n" +
                "\t\t\"name\": \"黑色\"\n" +
                "\t},{\n" +
                "\t\t\"id\": 2,\n" +
                "\t\t\"name\": \"M\"\n" +
                "\t},{\n" +
                "\t\t\"id\": 3,\n" +
                "\t\t\"name\": \"男\"\n" +
                "\t},{\n" +
                "\t\t\"id\": 1,\n" +
                "\t\t\"name\": \"红色\"\n" +
                "\t},{\n" +
                "\t\t\"id\": 2,\n" +
                "\t\t\"name\": \"X\"\n" +
                "\t},{\n" +
                "\t\t\"id\": 3,\n" +
                "\t\t\"name\": \"女\"\n" +
                "\t}\n" +
                "]\n" +
                "\n";

        // 将字符串解析为产品属性关系实体的列表
        List<PmsProductAttrRelVo> relVos = JSONArray.parseArray(str, PmsProductAttrRelVo.class);

        // 使用流操作和Collectors.groupingBy将数据按id分组
        Map<String, List<PmsProductAttrRelVo>> groupedByid = relVos.stream()
                .collect(Collectors.groupingBy(
                        map -> String.valueOf(map.getId()), // 分组键
                        Collectors.toList() // 收集器
                ));

        // 获取所有不同id的集合，用于后续生成所有可能的属性组合
        Set<Integer> uniqueids = new HashSet<>(groupedByid.keySet().stream()
                .map(Integer::parseInt)
                .collect(Collectors.toList()));

        // 初始化存储所有可能属性组合的列表
        List<Map<String, String>> combinations = new ArrayList<>();

        // 获取每个id对应的属性名称列表，并将其收集到一个二维列表中
        List<List<String>> idValues = uniqueids.stream()
                .map(id -> groupedByid.getOrDefault(String.valueOf(id), Collections.emptyList())
                        .stream()
                        .map(PmsProductAttrRelVo::getName)
                        .collect(Collectors.toList()))
                .collect(Collectors.toList());

        // 使用笛卡尔积算法生成所有可能的属性组合
        cartesianProduct(idValues).forEach(combination -> {
            Map<String, String> result = new LinkedHashMap<>();
            for (int i = 0; i < combination.size(); i++) {
                result.put(String.valueOf(uniqueids.toArray(new Integer[0])[i]), combination.get(i));
            }
            combinations.add(result);
        });

        // 输出计算结果
        System.out.println(JSONObject.toJSONString(combinations));
    }

    /**
     * 辅助方法：计算多个列表的笛卡尔积。
     * 输入：一个包含多个字符串列表的列表 lists，每个列表代表一个属性类别下的属性值集合。
     * 输出：一个列表，包含所有可能的属性组合。
     */
    private static List<List<String>> cartesianProduct(List<List<String>> lists) {
        if (lists == null || lists.isEmpty()) {
            return Collections.emptyList();
        }

        List<List<String>> result = new ArrayList<>();
        if (lists.size() == 1) {
            // 如果只有一个列表，则直接返回它的元素作为单元素列表
            for (String item : lists.get(0)) {
                result.add(Collections.singletonList(item));
            }
        } else {
            // 递归地计算除了第一个列表之外的笛卡尔积
            List<List<String>> restCartesian = cartesianProduct(lists.subList(1, lists.size()));
            // 将第一个列表中的每个元素与剩余笛卡尔积的每个列表组合起来
            for (String first : lists.get(0)) {
                for (List<String> rest : restCartesian) {
                    List<String> combination = new ArrayList<>(rest.size() + 1);
                    combination.add(first);
                    combination.addAll(rest);
                    result.add(combination);
                }
            }
        }
        return result;
    }

}
